package com.giftmail.server


import com.giftmail.handler.ServerHandler
import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.ChannelInitializer
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioServerSocketChannel
import io.netty.handler.codec.serialization.{ClassResolver, ClassResolvers, ObjectDecoder, ObjectEncoder}

class NettyServer {
  def bind(host:String,port:Int) :Unit = {
  //服务端线程池组NioEventLoopGroup
  //用于服务器接收客户端的连接
    val bossGroup = new NioEventLoopGroup()
  //用户进行SocketChannel的网络读写
    val workerGroup = new NioEventLoopGroup()

    try{
      //Netty用户启动NIO服务端的辅助启动类,降低服务端的开发复杂度
      val bootstrap = new ServerBootstrap()
      //将两个NIO线程组作为参数传入到ServerBootstrap
      bootstrap.group(bossGroup,workerGroup)
        //创建NioServerSocketChannel
        .channel(classOf[NioServerSocketChannel]) //相当于定义对象.class的反射
        //绑定I/O事件处理类(childHandler处理器)
        .childHandler(new ChannelInitializer[SocketChannel] {
        override def initChannel(ch: SocketChannel): Unit = {
          ch.pipeline().addLast(
            //自定义处理器(业务处理器)
            //改造:第四步:RPC之间传递的case class数据,必须是序列化和反序列化的数据,故,如下处理
            new ObjectEncoder,    //编码
            new ObjectDecoder(ClassResolvers.cacheDisabled(getClass.getClassLoader)),
            new ServerHandler
          )
        }
      })
      //绑定端口,调用sync方法等待绑定操作完成
      val channelFuture = bootstrap.bind(host,port).sync()
      //等待服务关闭
      channelFuture.channel().closeFuture().sync()

    }finally {
      //优雅的退出,释放线程池资源
      bossGroup.shutdownGracefully()
      workerGroup.shutdownGracefully()
    }

  }
}


object NettyServer{
  def main(args: Array[String]): Unit = {
    val host = args(0)
    val port = args(1).toInt
    val server = new NettyServer
    server.bind(host,port)

  }
}